package com.example.touch;

import java.security.spec.MGF1ParameterSpec;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import org.andengine.engine.Engine;
import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.entity.IEntity;
import org.andengine.entity.IEntityFactory;
import org.andengine.entity.modifier.MoveModifier;
import org.andengine.entity.modifier.MoveYModifier;
import org.andengine.entity.modifier.ParallelEntityModifier;
import org.andengine.entity.modifier.ScaleModifier;
import org.andengine.entity.modifier.SequenceEntityModifier;
import org.andengine.entity.particle.ParticleSystem;
import org.andengine.entity.particle.emitter.PointParticleEmitter;
import org.andengine.entity.particle.emitter.RectangleParticleEmitter;
import org.andengine.entity.particle.initializer.AlphaParticleInitializer;
import org.andengine.entity.particle.initializer.ColorParticleInitializer;
import org.andengine.entity.particle.initializer.GravityParticleInitializer;
import org.andengine.entity.particle.initializer.VelocityParticleInitializer;
import org.andengine.entity.particle.modifier.AlphaParticleModifier;
import org.andengine.entity.particle.modifier.ColorParticleModifier;
import org.andengine.entity.particle.modifier.ExpireParticleInitializer;
import org.andengine.entity.particle.modifier.IParticleModifier;
import org.andengine.entity.particle.modifier.RotationParticleModifier;
import org.andengine.entity.particle.modifier.ScaleParticleModifier;
import org.andengine.entity.primitive.Line;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.scene.CameraScene;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.Text;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.util.color.Color;
import org.andengine.util.math.MathUtils;
import org.andengine.util.modifier.IModifier;

import com.example.fruit.GameActivity;
import com.example.fruitpool.Boom;
import com.example.fruitpool.BoomPool;
import com.example.fruitpool.Fruit;
import com.example.fruitpool.FruitPool;
import com.example.fruitpool.Point;
import com.example.fruitpool.Pool;
import com.example.fruitpool.Pool.PoolObjectFactory;
import com.example.input.Input.TouchEvent;
import com.example.manager.ResourcesManager;
import com.example.manager.SceneManager;
import com.example.scene.GameScene;
import com.example.scene.ResultScene;
import com.example.scene.RingLeaderLevel;

import android.R.raw;
import android.util.Log;
import android.view.MotionEvent;
import android.view.animation.ScaleAnimation;


public class MultiTouchHandler implements TouchHandler {

	public boolean[] isTouched = new boolean[10];
	public int[] touchX = new int[10];
	public int[] touchY = new int[10];
	Pool<TouchEvent> touchEventPool;
	List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();
	List<TouchEvent> touchEventsBuffer = new ArrayList<TouchEvent>();
	private static MultiTouchHandler instance;
	GameScene mScene;
	ResourcesManager resourcesManager;
	VertexBufferObjectManager vbom;
	public MultiTouchHandler(ResourcesManager resourcesManager, VertexBufferObjectManager vbom, Scene mScene) {
		this.mScene = (GameScene) mScene;
		this.resourcesManager = resourcesManager; 
		this.vbom = vbom;
		PoolObjectFactory<TouchEvent> factory = new PoolObjectFactory<TouchEvent>() {
			public TouchEvent createObject() {
				return new TouchEvent();
			}
		};
		touchEventPool = new Pool<TouchEvent>(factory, 100);

		this.mScene.setOnSceneTouchListener(this);

	}
	
	public boolean isTouchDown(int pointer) {
		synchronized (this) {
			if (pointer < 0 || pointer >= 20)
				return false;
			else
				return isTouched[pointer];
		}
	}

	public int getTouchX(int pointer) {
		synchronized (this) {
			if (pointer < 0 || pointer >= 20)
				return 0;
			else
				return touchX[pointer];
		}
	}

	public int getTouchY(int pointer) {
		synchronized (this) {
			if (pointer < 0 || pointer >= 20)
				return 0;
			else
				return touchY[pointer];
		}
	}

	public List<TouchEvent> getTouchEvents() {
		synchronized (this) {
			int len = touchEvents.size();
			for (int i = 0; i < len; i++)
				touchEventPool.free(touchEvents.get(i));
			touchEvents.clear();
			touchEvents.addAll(touchEventsBuffer);
			touchEventsBuffer.clear();
			return touchEvents;
		}
	}

	static int ii = 0;
	StringBuilder builder = new StringBuilder();
	int x1, y1, x2, y2;
	// com.example.multitouchexample1.Point currPoint, prevPoint,currPoint1,
	// prevPoint1 = null;
	Point[] currPoint = new Point[10]; 
	Point[] prevPoint = new Point[10];
	Line line;
	int x1Convert = 0, y1Convert = 0, x2Convert = 0, y2Convert = 0; 
	
	public void convertTouch(int x1, int y1, int x2, int y2)
	{
	//	float wRate = (float) (1.0*CAMERA_WIDTH/width);
		//float hRate = (float) (1.0*CAMERA_HEIGHT/height);
		//float wRate = (float) (1.0*width/CAMERA_WIDTH);
		//float hRate = (float) (1.0*height/CAMERA_HEIGHT);
		
		x1Convert = (int) (x1*resourcesManager.wRate);
		y1Convert = (int) (y1*resourcesManager.hRate);
		x2Convert = (int) (x2*resourcesManager.wRate);
		y2Convert = (int) (y2*resourcesManager.hRate);
		
		Log.d("inconvert", x1+"->"+x1Convert+":"+y1+"->"+y1Convert);
	}
	boolean k=true;
	Boom boom;
	
	@Override
	public boolean onSceneTouchEvent(Scene pScene,org.andengine.input.touch.TouchEvent pSceneTouchEvent) {
		synchronized (this) {
			int action = pSceneTouchEvent.getAction() & MotionEvent.ACTION_MASK;//get action mouse
			int pointerIndex = (pSceneTouchEvent.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
			// int pointerId = pSceneTouchEvent.getPointerId(pointerIndex);
			int pointerId = pSceneTouchEvent.getMotionEvent().getPointerId(pointerIndex);
			// int pointerId = pSceneTouchEvent.getPointerID();
			Log.d("pointerId:", pointerId+"");
			Log.d("pointerIndex:", pointerIndex+"");
			TouchEvent touchEvent;

			switch (action) {
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_POINTER_DOWN:
				touchEvent = touchEventPool.newObject();
				touchEvent.type = TouchEvent.TOUCH_DOWN;
				touchEvent.pointer = pointerId;
				touchEvent.x = touchX[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getX(pointerIndex);
				touchEvent.y = touchY[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getY(pointerIndex);
				isTouched[pointerId] = true;
				touchEventsBuffer.add(touchEvent);
				// mScene.particleSystem.reset();
				/*prevPoint[pointerId] = new com.example.multitouchexample1.Point();
				prevPoint[pointerId].x = (int) pSceneTouchEvent.getMotionEvent().getX(pointerIndex);
				// prevPoint.x =
				// MultiTouchExample.CAMERA_WIDTH*prevPoint.x/MultiTouchExample.getSharedInstance().width;
				prevPoint[pointerId].y = (int) pSceneTouchEvent.getMotionEvent().getY(pointerIndex);*/
				
				currPoint[pointerId] = new Point();
				currPoint[pointerId].x = (int) pSceneTouchEvent.getMotionEvent().getX(pointerIndex);

				// currPoint.x =
				// MultiTouchExample.CAMERA_WIDTH*currPoint.x/MultiTouchExample.getSharedInstance().width;
				currPoint[pointerId].y = (int) pSceneTouchEvent.getMotionEvent().getY(pointerIndex);
				Log.d("ACTION_POINTER_DOWN->pointerId:", pointerId+"");
				break;

			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_POINTER_UP:
			case MotionEvent.ACTION_CANCEL:
				touchEvent = touchEventPool.newObject();
				touchEvent.type = TouchEvent.TOUCH_UP;
				touchEvent.pointer = pointerId;
				touchEvent.x = touchX[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getX(pointerIndex);
				touchEvent.y = touchY[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getY(pointerIndex);
				isTouched[pointerId] = false;
				touchEventsBuffer.add(touchEvent);
				// mScene.particleSystem.setParticlesSpawnEnabled(false);
				// hideAll();
				Log.d("ACTION_POINTER_UP->pointerId:", pointerId+"");
				k=true;
				//line.detachSelf();
				//mScene.detachChild(line);			
				break; 
 
			case MotionEvent.ACTION_MOVE:
				int pointerCount = pSceneTouchEvent.getMotionEvent().getPointerCount();
				Log.d("ACTION_MOVE->pointerCount", pointerCount+"");
				for (int i = 0; i < pointerCount; i++) {
					try {
						pointerIndex = i;
						pointerId = pSceneTouchEvent.getMotionEvent().getPointerId(pointerIndex);
						touchEvent = touchEventPool.newObject();
						touchEvent.type = TouchEvent.TOUCH_DRAGGED;
						touchEvent.pointer = pointerId;
						touchEvent.x = touchX[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getX(pointerIndex);
						touchEvent.y = touchY[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getY(pointerIndex);
						touchEventsBuffer.add(touchEvent);
						//Log.d("pointerCount:"+i, pointerId + ":" + touchEvent.x + ":"+ touchEvent.y);
						prevPoint[pointerId] = new Point();
						prevPoint[pointerId].x = (int) pSceneTouchEvent.getMotionEvent().getX(pointerIndex);

						// currPoint.x =
						// MultiTouchExample.CAMERA_WIDTH*currPoint.x/MultiTouchExample.getSharedInstance().width;
						prevPoint[pointerId].y = (int) pSceneTouchEvent.getMotionEvent().getY(pointerIndex);
						try {
							convertTouch(prevPoint[pointerId].x, prevPoint[pointerId].y,currPoint[pointerId].x, currPoint[pointerId].y);	
						} catch (Exception e) {
							;
						}
						
						//line = new Line(currPoint[pointerId].x, currPoint[pointerId].y, prevPoint[pointerId].x, prevPoint[pointerId].y, activity.getVertexBufferObjectManager());
						line = new Line(x2Convert,y2Convert,x1Convert,y1Convert,vbom);
						line.setLineWidth(3);
						line.setAlpha(0);
						//mScene.attachChild(line);
						if(k){
							/*resourcesManager.sliceWind.setVolume(1);
							resourcesManager.sliceWind.play();*/
							//resourcesManager.playSoundWind();
							k=false;
						}
						//Log.d("line:", "("+line.getX1()+":"+line.getY1()+"),("+line.getX2()+":"+line.getY2()+")");
						//synchronized (mScene.fruitList) 
						{								
							Log.d("countboom", GameScene.boomList.size() + "");
							final Iterator<Boom> booms = GameScene.boomList.iterator();
							
							// iterating over the targets
							while (booms.hasNext()) {
								
								boom = booms.next();
								//Log.d("fruit:", boom.sprit.getX()+":"+_target.sprit.getY());
							//	Log.d("a", targets.toString());
								// if target passed the left edge of the screen, then remove it
								// and call a fail
								if (boom.sprit.collidesWith(line)) {	
										Log.d("pos", boom.id);
										if(!isTouchIgnore){
										mScene.boomList.clear();
										mScene.fruitList.clear();
										//mScene.pauseTimerHandler();
										mScene.resetGame("crash");
										rung();
										}
									//mScene.slashBackGround();
						//			Thread.sleep(3000);
									
									break;
								 
								}
							}
							
							Iterator<Fruit> targets = GameScene.fruitList.iterator();
							Fruit _target;
							// iterating over the targets
							while (targets.hasNext()) {
								_target = targets.next();
								Log.d("fruit:", _target.sprit.getX()+":"+_target.sprit.getY());
							//	Log.d("a", targets.toString());
								// if target passed the left edge of the screen, then remove it
								// and call a fail
								if (_target.sprit.collidesWith(line)) {
								//	mScene.addEffectSlashFruit(_target.sprit);
									synchronized (_target) {
										resourcesManager.playSoundSlice();
									}
									createExplosion(_target.sprit.getX()+_target.sprit.getWidth()/2,_target.sprit.getY()+_target.sprit.getHeight()/2,_target.sprit.getParent());
									// removeSprite(_target, targets);
									if(!isTouchIgnore){
										String score = mScene.score;
										int s = Integer.parseInt(score);
										s++;
										mScene.score = s+"";
										Log.d("pos", mScene.score);
										//mScene.text.setText(mScene.score+"");
										mScene.setTextChange();
									}
									FruitPool.sharedFruitPool().onHandleRecycleItem(_target);
									//targets.remove();
									
									pScene.detachChild(_target.sprit);
									targets.remove();
									//mScene.detachChild(tar)
									// fail();
									//touch text
									if(RingLeaderLevel.isTouchFinal){
										RingLeaderLevel boss = RingLeaderLevel.getSharedInstance();
										String tag = (String) _target.sprit.getUserData();
										boss.processTag(tag);
										Log.d("pos1", tag);
									}
									break;
								}
							}
							//touch gift box
							if (isGiftBox) {
								RingLeaderLevel boss = RingLeaderLevel
										.getSharedInstance();
								Random ran = new Random();
								int r = ran.nextInt(2);
								r=1;
								if (line.collidesWith(boss.giftBox1)) {
									Log.d("pos", "1");
									openGiftBox(boss,r);
								} else if (line.collidesWith(boss.giftBox2)) {
									openGiftBox(boss,r);
								} else if (line.collidesWith(boss.giftBox3)) {
									openGiftBox(boss,r);
								}
							}
							
						} 
						currPoint[pointerId] = prevPoint[pointerId];
					} catch (Exception e) {
						//Log.d("pos", e.getMessage());
					}
					
				}
				break;
			}
			// Log.d("touch", "Asd");
			// updateTextView();
			
			return true;
		}
		
	}
	private void openGiftBox(RingLeaderLevel boss, int r) {
		mScene.resumeTimerHandler(true);
		isGiftBox = false;
		if(r==1)
			boss.textSpecial(boss.giftBox1);
			else if(r==0){
				boss.addInnings();
			}
	}

	public static boolean isTouchIgnore = false;
	public static boolean isGiftBox = false;
	public void rung(){
		MoveModifier[] mod=new MoveModifier[10];
		Random r=new Random();
		for(int j=0;j<10;j++)
		{
			mod[j]=new MoveModifier(0.07f, r.nextInt(30), r.nextInt(30), r.nextInt(30), r.nextInt(30));
		}
		mScene.backGroundSprite.registerEntityModifier(new SequenceEntityModifier(
				mod[0], mod[1], mod[2], mod[3], mod[4], mod[5],mod[6],mod[7],mod[8],mod[9]	
		) {

			@Override
			public void onModifierFinished(IModifier<IEntity> pModifier,
					IEntity pItem) {
				// TODO Auto-generated method stub
				super.onModifierFinished(pModifier, pItem);
				mScene.backGroundSprite.setPosition(0, 0);
				SceneManager.getInstance().loadResultScene(resourcesManager.engine);
				/*mScene.clearUpdateHandlers(); 
				mScene.isStopped = true;
				BoomPool.sharedBoomPool().onHandleRecycleItem(boom);
				booms.remove();
				CameraScene cam = new CameraScene(resourcesManager.camera);
				Sprite back = new Sprite(0, 0, resourcesManager.activity.CAMERA_WIDTH,
						resourcesManager.activity.CAMERA_HEIGHT ,resourcesManager.game_background_region, vbom);
				back.setAlpha(0.5f);
				cam.attachChild(back);
				Text result = new Text(0, 0, resourcesManager.font, "Game Over", vbom);
				final int x1 = (int) (resourcesManager.activity.CAMERA_WIDTH / 2 - result.getWidth() / 2);
				final int y1 = (int) (resourcesManager.activity.CAMERA_HEIGHT / 2 - result.getHeight() / 2);
				result.setPosition(x1, resourcesManager.activity.mCamera.getHeight() + result.getHeight());
				MoveYModifier mod = new MoveYModifier(2, result.getY(), y1) {
					@Override
					protected void onModifierFinished(IEntity pItem) {
						mScene.clearChildScene();
						SceneManager.getInstance().loadResultScene(resourcesManager.engine);
					}
				};
				result.registerEntityModifier(mod);
				cam.attachChild(result);
				cam.setBackgroundEnabled(false);
				
				mScene.setChildScene(cam,false,true,true);*/
			}
		});
	}
	private void createExplosion(final float posX, final float posY,final IEntity target) {
		int mNumPart = 15;
		int mTimePart = 2;
		PointParticleEmitter particleEmitter = new PointParticleEmitter(posX,posY);
		IEntityFactory<Sprite> recFact = new IEntityFactory<Sprite>() {
			@Override
			public Sprite create(float pX, float pY) {
				Sprite rect = new Sprite(pX, pY, resourcesManager.star_region, vbom);
				return rect;
			}

		};
		final ParticleSystem<Sprite> particleSystem = new ParticleSystem<Sprite>(recFact, particleEmitter, 500, 500, mNumPart);
		particleSystem.addParticleInitializer(new VelocityParticleInitializer<Sprite>(-50, 50, -50, 50));
		particleSystem.addParticleModifier(new AlphaParticleModifier<Sprite>(0,0.6f * mTimePart, 1, 0));
		particleSystem.addParticleModifier(new RotationParticleModifier<Sprite>(0,mTimePart, 0, 360));

		target.attachChild(particleSystem);
		target.registerUpdateHandler(new TimerHandler(mTimePart,
				new ITimerCallback() {
					@Override
					public void onTimePassed(final TimerHandler pTimerHandler) {
						particleSystem.detachSelf();
						target.sortChildren();
						target.unregisterUpdateHandler(pTimerHandler);
					}
				}));
	}
}
